/**************基于51单片机的数字音乐盒***********/

#include <REGX52.H>
#include "Tim.h"
#include "Delay.h"
#include "LCD1602.h"

/****定义按键引脚****/
sbit KEY1 = P1^0;
sbit KEY2 = P1^1;
sbit KEY3 = P1^2;
sbit KEY4 = P1^3;
sbit KEY5 = P1^4;

/****蜂鸣器****/
#define SPEED   500  //四分音符500ms
sbit Buzzer = P2^7;		//蜂鸣器引脚定义

//音符与索引对应表，P：休止符，L：低音，M：中音，H：高音，下划线：升半音符号#
#define P	0
#define L1	1
#define L1_	2	//Ctrl+shift+F可以替换变量字母
#define L2	3
#define L2_	4
#define L3	5
#define L4	6
#define L4_	7
#define L5	8
#define L5_	9
#define L6	10
#define L6_	11
#define L7	12
#define M1	13
#define M1_	14
#define M2	15
#define M2_	16
#define M3	17
#define M4	18
#define M4_	19
#define M5	20
#define M5_	21
#define M6	22
#define M6_	23
#define M7	24
#define H1	25
#define H1_	26
#define H2	27
#define H2_	28
#define H3	29
#define H4	30
#define H4_	31
#define H5	32
#define H5_	33
#define H6	34
#define H6_	35
#define H7	36

//索引与频率对照表
unsigned int FreqTable[]={
	0,
	63628,63731,63835,63928,64021,64103,64185,64260,64331,64400,64463,64528,
	64580,64633,64684,64732,64777,64820,64860,64898,64934,64968,65000,65030,
	65058,65085,65110,65134,65157,65178,65198,65217,65235,65252,65268,65283,
};

unsigned char FreqSelect,MusicSelect;

unsigned char code Music_HuaHai[]={
	//花海---周杰伦
	//音符,时值,	
	//1行号
	P,	4,	M1,	4,	M2,	4,	M3,	4,	M5,	4,	M5,	4+2,	M3,	4,	M2,	4,	M1,	4,	M2,	4,	M3,	4,	P,	4,	
	//2行号
	M1,	4,	M2,	4,	M3,	4,	M7,	4,	H1,	4,	H1,	4,	M7,	4,	M6,	4,	M5,	4,	M6,	4,	M5,	4,	P,	4,	
	//3行号
	M1,	4,	M2,	4,	M3,	4,	M5,	4,	M5,	4+2,	M3,	4,	M2,	4,	M1,	4,	M2,	4,	M1,	4,	P,	4,	
	//4行号
	M1,	4,	M2,	4,	M3,	4,	M5,	4,	M5,	4+2,	M4,	4,	M4,	4,	M3,	4,	H1,	4,	M3,	4,	M2,	4,	P,	4,

	//最后一行
	M1,	4,	M2,	4,	M3,	4,	M5,	4,	M1,	4,	M1,	4+2,	L7, 4,	L6, 4,	L7, 4,	M1,	4,
	
	0xFF

};

unsigned char code Music_Castle_in_the_Sky[]={
	//《天空之城》
	//音符,时值,	
	//1行号
	P,	4,	P,	4,	P,	4,	M6,	2,	M7,	2,	//每一小节 时值都是16	
	H1,	4+2,	M7,	2,	H1,	4,	H3,	4,	M7,	4+4+4,	M3,	2,	M3,	2,
	
	//2
	M6,	4+2,	M5,	2,	M6, 4,	H1,	4,	
	M5,	4+4+4,	M3,	4,	
	M4,	4+2,	M3,	2,	M4,	4,	H1,	4,	
	//3
	M3,	4+4,	P,	2,	H1,	2,	H1,	2,	H1,	2,	
	M7,	4+2,	M4_,2,	M4_,4,	M7,	4,	
	M7,	8,	P,	4,	M6,	2,	M7,	2,	
	//4
	H1,	4+2,	M7,	2,	H1,	4,	H3,	4,	
	M7,	4+4+4,	M3,	2,	M3,	2,	
	M6,	4+2,	M5,	2,	M6, 4,	H1,	4,	
	//5
	M5,	4+4+4,	M2,	2,	M3,	2,	
	M4,	4,	H1,	2,	M7,	2+2,	H1,	2+4,	
	H2,	2,	H2,	2,	H3,	2,	H1,	2+4+4,	
	//6
	H1,	2,	M7,	2,	M6,	2,	M6,	2,	M7,	4,	M5_,4,	
	M6,	4+4+4,	H1,	2,	H2,	2,	
	H3,	4+2,	H2,	2,	H3,	4,	H5,	4,	
	//7
	H2,	4+4+4,	M5,	2,	M5,	2,	
	H1,	4+2,	M7,	2,	H1,	4,	H3,	4,	
	H3,	4+4+4+4,
	
	//8
	M6,	2,	M7,	2,	H1,	4,	M7,	4,	H2,	2,	H2,	2,	
	H1,	4+2,	M5,	2+4+4,	
	H4,	4,	H3,	4,	H3,	4,	H1,	4,	
	//9
	H3,	4+4+4,	H3,	4,	
	H6,	4+4,	H5,	4,	H5,	4,	
	H3,	2,	H2,	2,	H1,	4+4,	P,	2,	H1,	2,
	
	//10
	H2,	4,	H1,	2,	H2,	2,	H2,	4,	H5,	4,	
	H3,	4+4+4,	H3,	4,	
	H6,	4+4,	H5,	4+4,
	
	//11
	H3,	2,	H2,	2,	H1,	4+4,	P,	2,	H1,	2,	
	H2,	4,	H1,	2,	H2,	2+4,	M7,	4,	
	M6,	4+4+4,	P,	4,
	
	0xFF
};

unsigned char code Music_3[] ={
	//《勇气大爆发》
	//音符,时值,	
	//1行号
	M3, 2, M3, 2, M3, 2, M3, 2,		M3, 2, M5, 2, M5, 2, M5, 2,		M5, 2, M4, 2,  M4, 2, M3, 2,  M4, 4, P, 4,
	M2, 2, M2, 2, M2, 2, M2, 2,		M2, 2, M3, 2, M4, 2, M4, 2,		M4, 2, M3, 2,  M3, 2, M4, 2,  M5, 2, P, 2, M6, 2, M5, 2,
	M6, 4, M1, 2, M1, 1, M1, 1, 	M6, 2, P , 2, M6, 2, 			M5, 2, M5, 2,  M5, 2, M6, 2,  M5,4,
	P , 2, M4, 1, M4, 1, 			M4, 2, M4, 2, M4, 2, 			M2, 2,  M2,  2,  P , 2, M6, 1,  M6, 1, M5, 2, M5, 2, M4, 2, M5, 4, P , 4,
	M3, 2, M3, 2, M3, 2, M3, 2, 	M3, 2, M5, 2, M5, 2, M5, 2,		M5, 2, M4, 2,  M4, 2, M3, 2,  M4, 2, P , 4,
	M2, 2, M2, 2, M2, 2, M2, 2,		M2, 2, M3, 2, M4, 2, M4, 2, 	M4, 2, M3, 2, M3, 2, M4, 2, 	M5, 2, P, 2, M6, 2, M5, 2, 
	M6, 4, M1, 2, M1, 2, 			M1, 2, M6, 2, P,  2, M6, 2,     M5, 2, M5, 2, M5, 2, M6, 2,  	
	M5, 5, P,  2, M4, 2, 			M4, 2, M4, 2, M4, 2, M4, 2, 	M2, 2, M1, 2, M2, 2, M1, 1, 	M1, 1, P,4,

	0xFF
};

/*变量-标志位*/
unsigned char Music_Mode = 0;		//模式--- 0 暂停(停止)，123分别代表第123首歌曲
unsigned char Music_Mode_Select;	//模式选择按键
void main()
{
	Timer0_Init();	//初始化默认停止计时，TR0 = 0;
	LCD_Init();		
	//开机动画
	LCD_ShowString(1,1,"Welcome");	//第一行第一列显示ABC
	LCD_ShowString(2,1," ");		//
	while(1)
	{
		
		if (0 == KEY1) 	{Music_Mode_Select = 1;MusicSelect = 0; LCD_ShowString(2,1,"Music 1");}	//按键1按下，选择模式0，MusicSelect乐谱索引清零，LCD提示 Music 1
		if (0 == KEY2) 	{Music_Mode_Select = 2;MusicSelect = 0; LCD_ShowString(2,1,"Music 2");}
		if (0 == KEY3) 	{Music_Mode_Select = 3;MusicSelect = 0; LCD_ShowString(2,1,"Music 3");}
		if (0 == KEY4)	//按键4开始播放所选择的乐曲
		{
			Music_Mode = Music_Mode_Select;	//将当前选择的模式赋值给Music_Mode变量
			TR0 = 1;	//音乐开启
		}
		if (0 == KEY5)	//如果按键5按下，暂停功能
		{	Music_Mode = 0;		}
		
		
		if (0 == Music_Mode)	TR0 = 0;	//暂停计时
		
		
		if (1 == Music_Mode)	//模式1 --- 歌曲1 --- 《花海》
		{
			LCD_ShowString(2,1,"Music 1");
			if(Music_HuaHai[MusicSelect]!=0xFF)//如果不是停止标志位
			{
				FreqSelect = Music_HuaHai[MusicSelect];//选择音符对应的频率
				MusicSelect++;
				Delay((SPEED/4)*Music_HuaHai[MusicSelect]);//十六分音符是125ms，选择音符对应的时值
				MusicSelect++;
				TR0=0;
				Delay(5);	//音符间短暂停顿
				TR0=1;
			}
			else	//如果是停止标志位
			{
				TR0=0;
//				while(1);//播放完死循环
			}
		}
		
		if (2 == Music_Mode)	//模式2 --- 歌曲2 --- 《天空之城》
		{
			LCD_ShowString(2,1,"Music 2");
			if(Music_Castle_in_the_Sky[MusicSelect]!=0xFF)//如果不是停止标志位
			{
				FreqSelect = Music_Castle_in_the_Sky[MusicSelect];//选择音符对应的频率
				MusicSelect++;
				Delay((SPEED/4)*Music_Castle_in_the_Sky[MusicSelect]);//十六分音符是125ms，选择音符对应的时值
				MusicSelect++;
				TR0=0;
				Delay(5);	//音符间短暂停顿
				TR0=1;
			}
			else	//如果是停止标志位
			{
				TR0=0;
//				while(1);//播放完死循环
			}
		}
		
		if (3 == Music_Mode)	//模式3 --- 歌曲3 --- 《勇气大爆发》
		{
			LCD_ShowString(2,1,"Music 3");
			if(Music_3[MusicSelect]!=0xFF)//如果不是停止标志位
			{
				FreqSelect = Music_3[MusicSelect];//选择音符对应的频率
				MusicSelect++;
				Delay((SPEED/4)*Music_3[MusicSelect]);//十六分音符是125ms，选择音符对应的时值
				MusicSelect++;
				TR0=0;
				Delay(5);	//音符间短暂停顿
				TR0=1;
			}
			else	//如果是停止标志位
			{
				TR0=0;
//				while(1);//播放完死循环
			}
		}
		
		
	}
}



/****定时器0的中断服务子函数****/
void Timer0_Routine() interrupt 1  
{
	//1ms进一次，2ms一周期，频率f=500Hz
	if(FreqTable[FreqSelect])	//如果不是休止符
	{
		TL0 = FreqTable[FreqSelect]%256;		//设置定时初值
		TH0 = FreqTable[FreqSelect]/256;		//设置定时初值
		Buzzer=!Buzzer;//翻转蜂鸣器IO口
	}

}



//LCD1602显示示例代码
	/*LCD_ShowChar(1,1,'A');
	LCD_ShowString(1,3,"Hello");//第一行第三列显示ABC
	LCD_ShowNum(1,9,123,3);//第一行第九列显示123占三位
	LCD_ShowSignedNum(1,13,-66,2);//
	LCD_ShowHexNum(2,1,0xA8,2);//第二行第一列显示A8，占两位
	LCD_ShowBinNum(2,4,0xAA,8);*/

